package abg.core.service.sys.impl;


import abg.core.common.cache.Cache;
import abg.core.common.cache.CacheKey;
import abg.core.common.util.StringKit;
import abg.core.domain.db.SysOrg;
import abg.core.domain.db.SysRole;
import abg.core.mapper.SysOrgMapper;
import abg.core.mapper.SysOrgMenuMapper;
import abg.core.mapper.SysRoleMapper;
import abg.core.mapper.SysRoleMenuMapper;
import abg.core.service.sys.SysMenuService;
import abg.core.service.sys.SysResService;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.AntPathMatcher;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;

import static abg.core.domain.db.table.SysOrgTableDef.SYS_ORG;
import static abg.core.domain.db.table.SysRoleTableDef.SYS_ROLE;


/**
 * TODO 资源相关实现
 */
@Slf4j
@Service
public class SysResServiceImpl implements SysResService {
    @Resource
    private Cache<String> cache;

    @Resource
    private SysOrgMapper sysOrgMapper;

    @Resource
    private SysOrgMenuMapper sysOrgMenuMapper;

    @Autowired
    private SysMenuService sysMenuService;

    @Resource
    private SysRoleMapper sysRoleMapper;

    @Resource
    private SysRoleMenuMapper sysRoleMenuMapper;

    //URI通配符规则匹配对象
    public static final AntPathMatcher pathMatcher = new AntPathMatcher();

    //角色和部门具备的资源
    @Override
    public HashSet<String> hasRes(Collection<String> roleIds, Collection<String> orgIds) {
        HashSet<String> res = new HashSet<>();
        res.addAll(roleHasRes(roleIds));
        res.addAll(orgHasRes(orgIds));
        return res;
    }

    //判断是否具备，URI访问资格
    @Override
    public boolean checkHasRes(String requestURI, Collection<String> roleIds, Collection<String> orgIds) {
        HashSet<String> hasResList = hasRes(roleIds, orgIds);
        for (String hasRes : hasResList) {
            boolean matchHas = pathMatcher.match(hasRes, requestURI);
            if (matchHas) return true;
        }
        return false;
    }


    //刷新 角色-资源 缓存
    @Override
    public void refreshRoleResCache(Collection<String> roleIds) {
        for (String roleId : roleIds) {
            refreshRoleResCache(roleId);
        }
    }


    //刷新 部门-资源 缓存
    @Override
    public void refreshOrgResCache(Collection<String> orgIds) {
        for (String orgId : orgIds) {
            refreshOrgResCache(orgId);
        }
    }

    //更新部门具备资源的缓存
    @Override
    public void refreshOrgResCache(String orgId) {
        //部门信息
        SysOrg sysOrg = sysOrgMapper.selectOneByQuery(QueryWrapper.create().and(SYS_ORG.ID.eq(orgId)));
        if (sysOrg == null) return;

        //部门自身,具备的资源 和 排除的资源
        ArrayList<String> orgHaseRes = StringKit.split(sysOrg.getRes());
        ArrayList<String> orgExcludeRes = StringKit.split(sysOrg.getResExclude());

        //部门关联菜单
        QueryWrapper menIdQuery = QueryWrapper.create().select("menu_id").eq("org_id", orgId);
        List<String> orgMenuIds = sysOrgMenuMapper.selectObjectListByQueryAs(menIdQuery, String.class);
        HashSet<String> treePathMenuHasRes = sysMenuService.getTreePathMenuHasRes(orgMenuIds);

        //
        //汇总全部具备资源
        HashSet<String> allHasRes = new HashSet<>();
        allHasRes.addAll(orgHaseRes);
        allHasRes.addAll(treePathMenuHasRes);
        HashSet<String> endRoleHasRes = StringKit.pathMatcherHasData(allHasRes, orgExcludeRes);

        //更新缓存
        String haseResStr = StringKit.join(endRoleHasRes, ",");
        cache.set(CacheKey.ORG_HASE_RES.key() + orgId, haseResStr);
        log.info("部门具备资源 {}", haseResStr);
    }


    //刷新 角色-资源 缓存
    @Override
    public void refreshRoleResCache(String roleId) {
        //角色自身 具备的资源 和 排除的资源
        SysRole sysRole = sysRoleMapper.selectOneByQuery(QueryWrapper.create().and(SYS_ROLE.ID.eq(roleId)));
        if (sysRole == null) return;
        ArrayList<String> roleHaseRes = StringKit.split(sysRole.getRes());
        ArrayList<String> roleExcludeRes = StringKit.split(sysRole.getResExclude());

        //角色关联菜单
        QueryWrapper menIdQuery = QueryWrapper.create().select("menu_id").eq("role_id", roleId);
        List<String> roleHasMenuIds = sysRoleMenuMapper.selectObjectListByQueryAs(menIdQuery, String.class);
        HashSet<String> treePathMenuHasRes = sysMenuService.getTreePathMenuHasRes(roleHasMenuIds);

        //
        //汇总全部具备资源
        HashSet<String> allHasRes = new HashSet<>();
        allHasRes.addAll(roleHaseRes);
        allHasRes.addAll(treePathMenuHasRes);
        HashSet<String> endRoleHasRes = StringKit.pathMatcherHasData(allHasRes, roleExcludeRes);

        //更新缓存
        String haseResStr = StringKit.join(endRoleHasRes, ",");
        cache.set(CacheKey.ROLE_HASE_RES.key() + roleId, haseResStr);
        log.info("角色具备资源 {}", haseResStr);
    }


    //查询所有和该菜单相关的 部门 和 角色，反向刷新资源
    private void refreshOrgMenuResCache(String menuId) {
//        //查询该菜单的上下级
//        QueryWrapper wrapper = new QueryWrapper();
//        wrapper.select("tree_path").like("tree_path", '"' + menuId + '"');
//        List<SysOrg> sysOrgs = sysOrgMapper.selectListByQuery(wrapper);
//        HashSet<Object> menuIds = new HashSet<>();
//        for (SysOrg sysOrg : sysOrgs) {
//            menuIds.addAll(JSONArray.parseArray(sysOrg.getTreePath()));
//        }
//
//        //查询与这些菜单有关系的部门
//        QueryWrapper roleMenuQuery = new QueryWrapper();
//        roleMenuQuery.in("menu_id", menuIds);
//        roleMenuQuery.select("role_id");
//        HashSet<String> roleIds = new HashSet<>(sysOrgMenuMapper.selectListByQueryAs(roleMenuQuery, String.class));
//
//        //更新这些部门缓存
//        refreshRoleResCache(roleIds);
    }


    //角色拥有资源
    public ArrayList<String> roleHasRes(String roleId) {
        if (roleId.isBlank()) return new ArrayList<>(0);

        String resStr = cache.get(CacheKey.ROLE_HASE_RES.key() + roleId);
        if (StringKit.isBlank(resStr)) return new ArrayList<>(0);

        return StringKit.split(resStr);
    }

    private ArrayList<String> roleHasRes(Collection<String> roleIds) {
        if (roleIds == null) return new ArrayList<>(0);

        HashSet<String> resList = new HashSet<>();
        for (String roleId : roleIds) {
            if (!roleId.isBlank()) resList.addAll(roleHasRes(roleId));
        }
        return new ArrayList<>(resList);
    }

    //部门拥有资源
    private ArrayList<String> orgHasRes(String orgId) {
        if (orgId.isBlank()) return new ArrayList<>(0);

        String resStr = cache.get(CacheKey.ORG_HASE_RES.key() + orgId);
        if (StringKit.isBlank(resStr)) return new ArrayList<>(0);

        return StringKit.split(resStr);
    }

    private ArrayList<String> orgHasRes(Collection<String> orgIds) {
        if (orgIds == null) return new ArrayList<>(0);

        HashSet<String> resList = new HashSet<>();
        for (String orgId : orgIds) {
            if (!orgId.isBlank()) resList.addAll(orgHasRes(orgId));
        }
        return new ArrayList<>(resList);
    }


}